using System;
using System.Collections.Generic;

using SBPweb.Common.Session;
using SBPweb.Common.Caching;

using SBPweb.PROvibe.Resources.Warehouse.Actor;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{
	public class ActorFactory
	{

		#region Private static string constants

		private static string CACHEKEY_ACTORS = "Warehouse.Actors";
		private static string CACHEKEY_ACTORS_INDEX_ID = "Warehouse.Actors.Index.Id";
		private static string CACHEKEY_ACTORS_INDEX_NAME = "Warehouse.Actors.Index.Name";

		private static string SESSIONKEY_ACTORS = "_Repository.Actors";

		#endregion

		#region Private fields

		private static ActorRepository mActorRepository
		{
			get
			{
				ActorRepository ret = SessionHandler.Get<ActorRepository>(SESSIONKEY_ACTORS);

				if (ret == null)
				{
					ret = new ActorRepository(ConfigurationManager.ConnectionStrings.Warehouse);
					SessionHandler.Put<ActorRepository>(SESSIONKEY_ACTORS, ret);
				}

				return ret;
			}
		}

		#endregion

        #region Constructor logic

        private ActorFactory()
        {
        }

        #endregion

		#region Repository handler methods

		#region Create

		public static Entities.Actor CreateActor(string name, string password, string email, DateTime lastActivity)
		{
			Resources.Entities.Actor actor = new Resources.Entities.Actor();

			actor.Email = email;
			actor.Name = name;
			actor.Password = password;
			actor.LastActivity = lastActivity;

			mActorRepository.Add(actor);

			return ConvertResourcesEntity(actor);
		}

		#endregion

		#region Read

		public static List<Entities.Actor> ReadActors()
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORS))
			{
				return CacheHandler.Retrieve<List<Entities.Actor>>(CACHEKEY_ACTORS);
			}

			List<Entities.Actor> actors = ConvertResourcesEntityList(mActorRepository.GetActors());

			if (isCached)
			{
				CacheHandler.Store<List<Entities.Actor>>(CACHEKEY_ACTORS, actors, ConfigurationManager.CacheExpirations.Warehouse.Actors);

				Dictionary<int, Entities.Actor> indexId = new Dictionary<int, Entities.Actor>();
				Dictionary<string, Entities.Actor> indexName = new Dictionary<string, Entities.Actor>();

				foreach (Entities.Actor actor in actors)
				{
					indexId.Add(actor.Id, actor);
					indexName.Add(actor.Name, actor);
				}

				CacheHandler.Store<Dictionary<int, Entities.Actor>>(CACHEKEY_ACTORS_INDEX_ID, indexId, ConfigurationManager.CacheExpirations.Warehouse.Actors);
				CacheHandler.Store<Dictionary<string, Entities.Actor>>(CACHEKEY_ACTORS_INDEX_NAME, indexName, ConfigurationManager.CacheExpirations.Warehouse.Actors);
			}

			return actors;
		}

		public static Entities.Actor ReadActorById(int actorId)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<int, Entities.Actor> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORS_INDEX_ID))
			{
				index = CacheHandler.Retrieve<Dictionary<int, Entities.Actor>>(CACHEKEY_ACTORS_INDEX_ID);
				if (index.ContainsKey(actorId))
				{
					return index[actorId];
				}
			}

			Resources.Entities.Actor resource = mActorRepository.GetActorById(actorId);
            Entities.Actor actor = null;
            if (resource != null)
            {
                actor = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(actorId, actor);
			}

			return actor;
		}

		public static Entities.Actor ReadActorByName(string actorName)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<string, Entities.Actor> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_ACTORS_INDEX_NAME))
			{
				index = CacheHandler.Retrieve<Dictionary<string, Entities.Actor>>(CACHEKEY_ACTORS_INDEX_NAME);
				if (index.ContainsKey(actorName))
				{
					return index[actorName];
				}
			}

			Resources.Entities.Actor resource = mActorRepository.GetActorByName(actorName);
            Entities.Actor actor = null;
            if (resource != null)
            {
                actor = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(actorName, actor);
			}

			return actor;
		}

		#endregion

		#region Update

		public static void UpdateActor(Entities.Actor actor)
		{
			mActorRepository.Update(actor);
		}

		#endregion

		#region Delete

		public static void DeleteActor(int actorId)
		{
			mActorRepository.Remove(actorId);
		}

		public static void DeleteActor(Entities.Actor actor)
		{
			DeleteActor(actor.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.Actor> ConvertResourcesEntityList(List<Resources.Entities.Actor> list)
		{
			return list.ConvertAll<Entities.Actor>(new Converter<Resources.Entities.Actor, Entities.Actor>(ConvertResourcesEntity));
		}

		internal static Entities.Actor ConvertResourcesEntity(Resources.Entities.Actor actor)
		{
			return new Entities.Actor(actor);
		}

		#endregion

	}
}
